package adaptive.opencom;

import OpenCOM.ICFMetaInterface;
import OpenCOM.ILifeCycle;
import OpenCOM.IOpenCOM;
import OpenCOM.IUnknown;
import OpenCOM.OpenCOM;
import android.os.Handler;
import android.util.Log;

/*
 * This class is used to group the OpenCom components and to realize binds and unbinds
 * */
public class OpenComManager {
	private static OpenComManager sInstance; // Singleton Pattern
	
	private ICFMetaInterface mAdaptiveAppCFMI;
	private IAdaptiveApp mAdaptiveApp;
	private IEventMonitor mEventMonitor;
	
	/*
	 * We can only have one OpenComManager
	 * */
	public static OpenComManager getInstance() {
		if(sInstance == null)
			sInstance = new OpenComManager();
		
		return sInstance;
	}
	
	/* 
	 * A private constructor because the Singleton Pattern
	 * */
	private OpenComManager() {		
		initOpenCom();
	}

	/*
	 * Here is make some initialization stuff
	 * */
	private void initOpenCom() {
		Log.d("BEFORE_TIME", "OpenCom");
		IOpenCOM pIOCM = createOpenCOMRuntime();
		
		IUnknown adaptiveAppFram = createAdaptiveAppFramework(pIOCM);
		
		if(!createFrameworkArchicteture()) {
			Log.d("Transaction Error", "Invalid Archicteture");
		} else {
			// Get the two interface of the Adaptive Application Framework
			mAdaptiveApp = (IAdaptiveApp) adaptiveAppFram.QueryInterface("adaptive.opencom.IAdaptiveApp");
			mEventMonitor = (IEventMonitor) adaptiveAppFram.QueryInterface("adaptive.opencom.IEventMonitor");
			//Log.d("Transaction Ok", "ok");
			/*
			List<AdaptationRequest> requests = mAdaptiveApp.adaptationRequest();
			for(AdaptationRequest ar : requests)
				Log.d("AdaptationRequest", ar.toString());
			*/
		}
		Log.d("AFTER_TIME", "OpenCom");
	}

	/**
	 * @return
	 */
	private boolean createFrameworkArchicteture() {
		// Transaction where we initialize the framework components and theirs connections
		mAdaptiveAppCFMI.init_arch_transaction();
			IUnknown adaptiveAppUnk = 
					mAdaptiveAppCFMI.create_component("adaptive.opencom.AdaptiveAppComponent", "MyAdaptiveApp");
			IUnknown eventMonitorUnk = 
					mAdaptiveAppCFMI.create_component("adaptive.opencom.EventMonitorComponent", "MyEventMonitor");
			/*
			IUnknown threeErrorKeyboardPolicyUnk =
					mAdaptiveAppCFMI.create_component("adaptive.opencom.ThreeErrorKeyboardPolicyComponent", 
							"MyThreeErrorKeyboardPolicy");
			*/
			IUnknown proximityPolicyUnk = 
					mAdaptiveAppCFMI.create_component("adaptive.opencom.ThreeErrorProximityKeyboardPolicyComponent",
						"MyProximityPolicy");
			
			/*
			mAdaptiveAppCFMI.local_bind(adaptiveAppUnk, threeErrorKeyboardPolicyUnk, 
					"adaptive.opencom.IAdaptationPolicy");
			*/
			mAdaptiveAppCFMI.local_bind(adaptiveAppUnk, proximityPolicyUnk, 
					"adaptive.opencom.IAdaptationPolicy");
			/*
			mAdaptiveAppCFMI.local_bind(threeErrorKeyboardPolicyUnk, eventMonitorUnk, 
					"adaptive.opencom.IEventMonitor");
			*/
			mAdaptiveAppCFMI.local_bind(proximityPolicyUnk, eventMonitorUnk, 
					"adaptive.opencom.IEventMonitor");
			
			mAdaptiveAppCFMI.expose_interface("adaptive.opencom.IAdaptiveApp", adaptiveAppUnk);
			mAdaptiveAppCFMI.expose_interface("adaptive.opencom.IEventMonitor", eventMonitorUnk);
		return mAdaptiveAppCFMI.commit_arch_transaction();
	}

	/**
	 * @param pIOCM
	 * @return
	 */
	private IUnknown createAdaptiveAppFramework(IOpenCOM pIOCM) {
		// Framework and Accept Initialization and Activation
		IUnknown adaptiveAppFram = 
				(IUnknown) pIOCM.createInstance("adaptive.opencom.AdaptiveAppFramework", "MyAdaptiveAppFramework");
		ILifeCycle adaptiveAppFramLife = (ILifeCycle) adaptiveAppFram.QueryInterface("OpenCOM.ILifeCycle");
		adaptiveAppFramLife.startup(pIOCM);		
		
		IUnknown adaptiveAppAccept =
				(IUnknown) pIOCM.createInstance("adaptive.opencom.AdaptiveAppAccept", "MyAdaptiveAppAccept");
		ILifeCycle adaptiveAppAcceptLife = (ILifeCycle) adaptiveAppAccept.QueryInterface("OpenCOM.ILifeCycle");
		adaptiveAppAcceptLife.startup(pIOCM);
		
		// Connection between the Framework and the Accept
		/*long connID_adaptiveAppFram_Acc = */pIOCM.connect(adaptiveAppFram, adaptiveAppAccept, "OpenCOM.IAccept");
		
		mAdaptiveAppCFMI = 	
				(ICFMetaInterface) adaptiveAppFram.QueryInterface("OpenCOM.ICFMetaInterface");
		return adaptiveAppFram;
	}

	/**
	 * @return
	 */
	private IOpenCOM createOpenCOMRuntime() {
		OpenCOM runtime = new OpenCOM();
		IOpenCOM pIOCM = (IOpenCOM) runtime.QueryInterface("OpenCOM.IOpenCOM");
		return pIOCM;
	}
	
	public IAdaptiveApp getAdaptiveApp() {
		return mAdaptiveApp;
	}
	
	public IEventMonitor getEventMonitor() {
		return mEventMonitor;
	}
}
